Coming from previous design of having all deltas be bidirectional
Current format for operations is
tuple[ name, data]
this isnt enforced its just what ive been doing
they are stored in a list as
tuple[ type| None, list[ tuple[ transformOperationId, transformData]]]
version types can currently either be INIT| FULL| DELTA| FULL_WITH_DELTA
if we had unidirectional deltas| we would have INIT| FULL| FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
So calculateDeltaData
needs to know the desired direction
if we wish for a FULL_WITH_BACKWARDS_DELTA
save then we desire a backwards delta
otherwise we want a normal delta save and so
so the save function takes a desired: FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
and calls calculateDeltaData
with a desired TransformType
of FORWARDS| BIDIRECTIONAL| BACKWARDS
calculateDeltaData
does some initial checks and returns and then finds a ConstructionSet
for the type
the ConstructionSet.deltaConstruction
takes the two instances and returns ( TransformType
, data)
they could take a preferred TransformType
which is None
by default
one way they could implement this is that when detaConstruction
encounters a situation which could result in branching types
of TransformType
it uses the preferred
Every operation needs to support bidirectional, ( forwards, backwards) but some may store the data in the same manner
In this case, deltaConstruction
can return bidirecitonal as this signals that the most traversible option is available
deconstructVersionDataChain
and applyDataTransform
need to change
deconstructVersionDataChain
will still return a valid sequence but it will possibly be made of uni and bidirectional deltas
when applying data changes in a line now, we will encounter unidirectional deltas
class Directionality( IntFlag):
BIDIRECTIONAL= auto()
UNIDIRECTIONAL= auto()
the ConstructionSet
s can now have a function called applyDeltas
which takes a group of delta transforms of a specific directionality
applyDataTransform
currently takes typeAndTransforms: deltaTransforms
it only needs to take the type once, as it should only ever be passed operations from a singular type
so it should take ( object: Any, typez: type, operations: Sequence[ Sequence[ Directionality, Sequence[ Sequence[ transformOperationId, transformData]]]], direction: OperationDirection)
and within it should call ConstructionSet.applyDeltas
for each Directionality
block
so ConstructionSet.applyDeltas
should take ( object: Any, directionality: , operations: Sequence[ Sequence[ transformOperationId, transformData]])
The design of preferred type passing seems a little weak
We can specify either a transform type or a commit type
Transform type delta s are BIDIRECTIONAL| UNIDIRECTIONAL| NONE| FULL
Commit types are those specified above, INIT| FULL| FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
constructed bidirectional transforms
when specifying the preferred do we specify q to w? or w to q if no preferred and only bidirectional like before it is implied q to w forwards and w to q backwards so maybe bidirectional needs an application direction of q to w or w to q unidirectional are constructed with a specific direction
i think in some circumstances if the preferred isnt available then we want to fallback to a full change in others we could accept bidirectional in place of unidirectional, unidirectional in place of bidirectional, maybe these desires could be fully specified using a sequence of acceptable outcomes, and if none can be fulfilled then it falls to a full change there is fallback behaviour for no sequence specified
the issue with running it once, determining the output and then rerunning is that the conversion set may have to run extra processes whereas if the order of desired outcomes was known to the conversion function then it could quickly decide on the outcome. maybe then a preference can be specified as well as a fallback value which either falls back to the other directionality than the prefferred and then to full or it directly falls back to a full transform so
class TransformFallback( IntFlag):
OPPOSITE_DIRECTIONALITY_THEN_FULL= auto()
FULL= auto()
So LTSD.save can take a preffered version type from these specific CommitType s: FORWARDS_DELTA| BIDIRECTIONAL_DELTA| FULL_WITH_BACKWARDS_DELTA
if forwards then we desire a unidirectional delta, if none can be found then we could fall back to bidirectional or full, either one really
save could take a fallback value it is currently relativelty unknown where it will be called from to initiate the different commit types, i envision an optimisation process which could reduce load times by constructing FULL_WITH_BACKWARDS_DELTA commits on data that has a large amount of subsequent deltas, bidirectional or forward could be discerned between by a software aspect seeking to optimise each individual version, maybe one that doesnt care about backwards traversing on the data could only use FORWARDS_DELTA
calculateDeltaData can take a preffered delta transform type form these TransformType s: UNIDIRECTIONAL| BIDIRECTIONAL
as well as a fallback of any from TransformFallback
DeltaTransformSet.deltaConstruction can take a preffered delta transform type form these TransformType s: UNIDIRECTIONAL| BIDIRECTIONAL
as well as a fallback of any from TransformFallback
UNIDIRECTIONAL s are calculated as q to w BIDIRECTIONAL s can be applied as ( q to w)| ( w to q)
So now need to redesign save
, calculateDeltaData
, DeltaTransformSet.deltaConstruction
save
needs to call calculateDeltaData
with UNIDIRECTIONAL
if FORWARDS_DELTA
needs to call calculateDeltaData
with BIDIRECTIONAL
if BIDIRECTIONAL_DELTA
needs to call calculateDeltaData
with UNIDIRECTIONAL
if FULL_WITH_BACKWARDS_DELTA
How the output is managed is dependant on the transform type of the output as well as the preferred CommitType passed to save
FULL
, NONE
, BIDIRECTIONAL
is the same result regardless
if the resultant TransformType
is UNIDIRECTIONAL
then:
if the preffered CommitType
is FORWARDS
then we are just using the returned data as a forwards delta
if the preffered CommitType
is FULL_WITH_BACKWARDS
then we need to use the full data and the returned data
calculateDeltaData
is mostly a passthrough to either basic returns or DeltaTransformSet.deltaConstruction
DeltaTransformSet.deltaConstruction
can return:
tuple[ TransformType, tuple[ type| None, list[ tuple[ transformOperationId, transformData]]]| None| Any]
This doesnt need to change
delta transforms of both directionalities can return list[ tuple[ transformOperationId, transformData]]]
all elements of the sequence should be of the same directionality
this includes any recursively contained delta lists
Due to this recursive requirement, if the passed fallback to the containing level is FULL
then that also must be the case for the called contained
If the contained cannot match the prefference of the container then
if FULL
is active then the contained must not default to the opposite of the preferred delta type
if OPPOSITE_DIRECTIONALITY_THEN_FULL
is active then the containd should fallback to the opposite of the preffered and then full
i think this means that the contained fallback should match the fallback of the container
the preffered of the contained should match the preferred of the container
if this is enforced by calculateDeltaData
then we should be fine with just specifying the input prefferred
and fallback
for the contained
in the future it could also be made so that individual transforms in the delta list are either uni or bi directional